layout.tsx 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. import Image from "next/image";
  2. import { Inter, Permanent_Marker } from "next/font/google";
  3. import { GeistSans } from "geist/font/sans";
  4. import { GeistMono } from "geist/font/mono";
  5. import { cn } from "@/shared/lib/utils";
  6. import { getServerUrl } from "@/shared/lib/server-url";
  7. import { FB_PIXEL_ID } from "@/shared/lib/facebook/fb-pixel";
  8. import { SiteConfig } from "@/shared/config/site-config";
  9. import { Header } from "@/features/layout/Header";
  10. import { Footer } from "@/features/layout/Footer";
  11. import { TailwindIndicator } from "@/components/utils/TailwindIndicator";
  12. import { NextTopLoader } from "@/components/ui/next-top-loader";
  13. import FacebookPixel from "@/components/FacebookPixel";
  14. import { Providers } from "./providers";
  15. import type { ReactElement } from "react";
  16. import type { Metadata } from "next";
  17. import "@/shared/styles/globals.css";
  18. export const metadata: Metadata = {
  19. title: SiteConfig.title,
  20. description: SiteConfig.description,
  21. metadataBase: new URL(getServerUrl()),
  22. };
  23. const inter = Inter({
  24. subsets: ["latin"],
  25. variable: "--font-inter",
  26. display: "swap",
  27. });
  28. const permanentMarker = Permanent_Marker({
  29. weight: "400",
  30. subsets: ["latin"],
  31. variable: "--font-permanent-marker",
  32. display: "swap",
  33. });
  34. export const preferredRegion = ["fra1", "sfo1", "iad1"];
  35. interface RootLayoutProps {
  36. params: Promise<{ locale: string }>;
  37. children: ReactElement;
  38. }
  39. export default async function RootLayout({ params, children }: RootLayoutProps) {
  40. const { locale } = await params;
  41. return (
  42. <>
  43. <html className="h-full" dir="ltr" lang={locale} suppressHydrationWarning>
  44. <head>
  45. <meta charSet="UTF-8" />
  46. <meta content="width=device-width, initial-scale=1" name="viewport" />
  47. {/* SEO */}
  48. <meta content="index, follow" name="robots" />
  49. <meta content="Workout Cool" name="author" />
  50. {/* Favicon */}
  51. <link href="/apple-touch-icon.png" rel="apple-touch-icon" sizes="180x180" />
  52. <link href="/images/favicon-32x32.png" rel="icon" sizes="32x32" type="image/png" />
  53. <link href="/images/favicon-16x16.png" rel="icon" sizes="16x16" type="image/png" />
  54. <link href="/images/favicon.ico" rel="shortcut icon" />
  55. {/* Open Graph */}
  56. <meta content={SiteConfig.title} property="og:title" />
  57. <meta content={SiteConfig.description} property="og:description" />
  58. <meta content={"https://www.workout.cool"} property="og:url" />
  59. <meta content="website" property="og:type" />
  60. <meta content={`${getServerUrl()}/images/default-og-image_${locale}.png`} property="og:image" />
  61. {/* Twitter */}
  62. <meta content="summary_large_image" name="twitter:card" />
  63. <meta content="@workout_cool" name="twitter:site" />
  64. <meta content={SiteConfig.title} name="twitter:title" />
  65. <meta content={SiteConfig.description} name="twitter:description" />
  66. <meta content={`${getServerUrl()}/images/default-og-image_${locale}.png`} name="twitter:image" />
  67. {/* Canonical */}
  68. <link href="https://www.workout.cool" rel="canonical" />
  69. {/* Open Graph Locale */}
  70. <meta content={locale === "fr" ? "fr_FR" : "en_US"} property="og:locale" />
  71. <meta content="fr_FR" property="og:locale:alternate" />
  72. <meta content="en_US" property="og:locale:alternate" />
  73. <noscript>
  74. <Image
  75. alt="Facebook Pixel"
  76. height="1"
  77. src={`https://www.facebook.com/tr?id=${FB_PIXEL_ID}&ev=PageView&noscript=1`}
  78. style={{ display: "none" }}
  79. width="1"
  80. />
  81. </noscript>
  82. </head>
  83. <body
  84. className={cn(
  85. "flex flex-col justify-between items-center p-8 min-h-screen max-sm:p-0 max-sm:min-h-full text-sm/[22px] font-normal text-black antialiased dark:text-gray-500",
  86. GeistMono.variable,
  87. GeistSans.variable,
  88. inter.variable,
  89. permanentMarker.variable,
  90. )}
  91. style={{
  92. backgroundImage:
  93. "radial-gradient(circle at 82% 60%, rgba(59, 59, 59,0.06) 0%, rgba(59, 59, 59,0.06) 69%,transparent 69%, transparent 100%),radial-gradient(circle at 36% 0%, rgba(185, 185, 185,0.06) 0%, rgba(185, 185, 185,0.06) 59%,transparent 59%, transparent 100%),radial-gradient(circle at 58% 82%, rgba(183, 183, 183,0.06) 0%, rgba(183, 183, 183,0.06) 17%,transparent 17%, transparent 100%),radial-gradient(circle at 71% 32%, rgba(19, 19, 19,0.06) 0%, rgba(19, 19, 19,0.06) 40%,transparent 40%, transparent 100%),radial-gradient(circle at 77% 5%, rgba(31, 31, 31,0.06) 0%, rgba(31, 31, 31,0.06) 52%,transparent 52%, transparent 100%),radial-gradient(circle at 96% 80%, rgba(11, 11, 11,0.06) 0%, rgba(11, 11, 11,0.06) 73%,transparent 73%, transparent 100%),radial-gradient(circle at 91% 59%, rgba(252, 252, 252,0.06) 0%, rgba(252, 252, 252,0.06) 44%,transparent 44%, transparent 100%),radial-gradient(circle at 52% 82%, rgba(223, 223, 223,0.06) 0%, rgba(223, 223, 223,0.06) 87%,transparent 87%, transparent 100%),radial-gradient(circle at 84% 89%, rgba(160, 160, 160,0.06) 0%, rgba(160, 160, 160,0.06) 57%,transparent 57%, transparent 100%),linear-gradient(90deg, rgb(254,242,164),rgb(166, 255, 237))",
  94. }}
  95. suppressHydrationWarning
  96. >
  97. <Providers locale={locale}>
  98. <NextTopLoader color="#FF5722" delay={100} showSpinner={false} />
  99. {/* Main Card Container */}
  100. <div className="card bg-base-100 shadow-xl w-full max-w-3xl max-sm:rounded-none max-sm:h-full">
  101. <div className="card-body p-0">
  102. <Header />
  103. <div className="px-2 sm:px-6 pb-6">{children}</div>
  104. </div>
  105. <Footer />
  106. </div>
  107. <TailwindIndicator />
  108. <FacebookPixel />
  109. </Providers>
  110. </body>
  111. </html>
  112. </>
  113. );
  114. }